<html>
<head><meta charset="utf-8"><title>UB and non-determinism and I/O · t-lang/wg-unsafe-code-guidelines · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/index.html">t-lang/wg-unsafe-code-guidelines</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/UB.20and.20non-determinism.20and.20I.2FO.html">UB and non-determinism and I/O</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="162029617"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/UB%20and%20non-determinism%20and%20I/O/near/162029617" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/UB.20and.20non-determinism.20and.20I.2FO.html#162029617">(Mar 29 2019 at 09:14)</a>:</h4>
<p><span class="user-mention" data-user-id="116155">@Jake Goulding</span> </p>
<blockquote>
<p>you understood me correctly. I was under the impression that Rust was taking the position of "if any code flow path could cause UB, it is always UB".</p>
</blockquote>
<p>"if any code flow path could cause UB, it is always UB" is correct, but it does not mean what you (seem to) think it means.<br>
it means that a program like <code>let x = Box::new(0); if Box::into_raw(x) as usize % 512 == 0 { trigger_ub(); }</code> has UB because the allocator is non-deterministic, and the compiler can decide for the allocator that it will pick a sufficiently aligned address here, and then take the then-branch.<br>
however, "if any code flow path could cause UB, it is always UB" does <em>not</em> mean that <code>let b = read_boolean_from_stdin(); if b { trigger_ub(); }</code> always has UB! Here, there is no non-deterministic choice the compiler can affect; the choice is made by the outside world, it might be deterministic or whatever, and the compiler has to respect that. If that program is only ever run in an environment where <code>b</code> ends up <code>false</code>, there is no UB as the branch is never taken!</p>
<p>Formally speaking, there are two kinds of choices in a program:<br>
<em>Internal choice</em> is when the semantics of the program say "this or that may happen and there is no way for the programmer or user to influence that". Examples include the memory allocator and the thread scheduler. The compiler is allowed to <em>refine</em> this choice, meaning it is allowed to take away certain possibilities here, like in my first example above where the compiler decided that the allocator will pick an address that is 512-aligned. (But then the entire execution has to be consistent with that refined choice!)<br>
In contrast, <em>external choice</em> is when the program interacts with the outside world and receives inputs from there. The compiler cannot affect what inputs will come. So if a program has UB only in case of certain malformed inputs, then the compiler has to translate it in a way that the resulting binary behaves just like the original program did <em>for any input that did not trigger UB</em>. You can think of the program as representing an answer to every possible question from the outside, like in my 2nd example above "input <code>false</code>? answer: nothing happens, program terminates" and "input <code>true</code>? answer: UB". All the input-answer-input-answer traces without UB must be preserved by the compiler.</p>
<p>That got longer than I expected... I hope it makes some sense?</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>